/****************************************************************************************
 ** Server is an application to manage several clients inside a thread.
 ** Copyright (C) 2013  Francesc Martinez <es.linkedin.com/in/cescmm/en>
 **
 ** This library is free software; you can redistribute it and/or
 ** modify it under the terms of the GNU Lesser General Public
 ** License as published by the Free Software Foundation; either
 ** version 2.1 of the License, or (at your option) any later version.
 **
 ** This library is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ** Lesser General Public License for more details.
 **
 ** You should have received a copy of the GNU Lesser General Public
 ** License along with this library; if not, write to the Free Software
 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 ***************************************************************************************/
 
#include <QDateTime>
#include "ClientThread.h"
#include <QDebug>

ClientThread::ClientThread(QObject *parent) : QThread(parent)
{
	quit = false;
	qRegisterMetaType<QAbstractSocket::SocketError>();
}

void ClientThread::setServer(QString ip, int port)
{
	_ip = ip;
	_port = port;
}

void ClientThread::run()
{
	client = new QTcpSocket();

	connect(client, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
	connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
	connect(client, SIGNAL(connected()), this, SIGNAL(wasConnected()), Qt::DirectConnection);
	connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));

	client->connectToHost(_ip, _port);
	client->waitForConnected(10000);

	while (!quit)
	{
		client->waitForReadyRead(1);
		for (int i = msgToWrite.size() - 1; i >= 0; i--)
		{
			client->write(msgToWrite.at(i));
			qDebug() << "Output[" << msgToWrite.at(i).size() << "]: " << msgToWrite.at(i).toHex();
			msgToWrite.removeAt(i);
		}
	}

	client->disconnectFromHost();
	client->waitForDisconnected(3000);
}

void ClientThread::closeConnection()
{
	quit = true;
}

void ClientThread::readyRead()
{
    emit receivedMessage(client->readAll());
}

void ClientThread::disconnected()
{
	client->deleteLater();
	quit = true;
	emit wasDisconnected();
}

void ClientThread::sendMessage(const QByteArray &msg)
{
	msgToWrite.prepend(msg);
}

void ClientThread::onError(QAbstractSocket::SocketError err)
{
	QString errMsg;
	switch(err){
		case QAbstractSocket::SocketTimeoutError: return;
		case QAbstractSocket::ConnectionRefusedError:
			errMsg = QString(tr("Connection with %1:%2 was refused")).arg(_ip).arg(_port);
			break;
		case QAbstractSocket::RemoteHostClosedError:
			errMsg = QString(tr("Server %1:%2 closed connection")).arg(_ip).arg(_port);
			break;
		case QAbstractSocket::HostNotFoundError:
			errMsg = QString(tr("Server %1:%2 not found")).arg(_ip).arg(_port);
			break;
		case QAbstractSocket::NetworkError:
			errMsg = QString(tr("Network error")).arg(_ip).arg(_port);
			break;
		default:
			errMsg = QString(tr("Socket error [code:%1]")).arg(err);
	}

	emit connectionError(errMsg);
}
